package com.mlh.backtracking;

/**
 * @author 缪林辉
 * @date 2024/4/8 11:44
 * @DESCRIPTION
 */

// 编写一个程序，通过填充空格来解决数独问题。
// 数独的解法需 遵循如下规则：
// 数字 1-9 在每一行只能出现一次。
// 数字 1-9 在每一列只能出现一次。
// 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。（请参考示例图）
// 数独部分空格内已填入了数字，空白格用 '.' 表示。
public class 解数独 {
    char[][] board;
    public void method1(char[][] board) {
        this.board = board;
        recursion();
    }
    //看代码随心录的代码写出
    //他与N皇后问题不一样，N皇后每行只填一个皇后
    //而这个每行都是要填满的
    //他们两个抽象树结构是不一样的，可以思考一下
    //解数独才是真正意义上的二维  N皇后其实还不能算作二维
    //去看了代码随想录的抽象树结构 本题就能一目了然
    public boolean recursion() {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (board[i][j] == '.') {
                    for (char k = '1'; k <= '9'; k++) {
                        if (isValid(i, j, k , board)) {
                            board[i][j] = k;
                            //循环里面加入这个if 适用于哪些不需要把全部可能遍历一遍的题目
                            //只需要找到一种解 就可以返回
                            if (recursion()) {
                                return true;
                            }
                            //回溯
                            board[i][j] = '.';
                        }
                    }
                    // 9个数都试完了，都不行，那么就返回false
                    return false;
                }
            }
        }
        //走到这里表示board中所有的数字已经填入，找出解，返回true
        return true;
    }

    //判断位置上写value是否古河规则
    public boolean isValid(int row, int col, char value, char[][] board) {
        // 检查行是否合法
        for (int i = 0; i < 9; i++) {
            if (board[row][i] == value) {
                return false;
            }
        }
        // 检查列是否合法
        for (int i = 0; i < 9; i++) {
            if (board[i][col] == value) {
                return false;
            }
        }
        // 检查3x3宫内是否合法
        int row3 = (row / 3) * 3;
        int col3 = (col / 3) * 3;
        for (int i = row3; i < row3 + 3; i++) {
            for (int j = col3; j < col3 + 3; j++) {
                if (board[i][j] == value) {
                    return false;
                }
            }
        }
        return true;
    }
}
